
#include "app_sr.h"
#include "esp_lvgl_port.h"
#include "lvgl.h"
#include "esp_log.h"
#include "esp_wn_iface.h"
#include "esp_wn_models.h"
#include "esp_afe_sr_iface.h"
#include "esp_afe_sr_models.h"
#include "esp_mn_iface.h"
#include "esp_mn_models.h"
#include "esp_mn_speech_commands.h"
#include "model_path.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_process_sdkconfig.h"
#include "audio_player.h"
#include "audio.h"
#include "md_languages.h"
#include "ui_setting.h"
#include "func_ui.h"

static const char *TAG = "app_sr";

static bool carry_command = false;

    srmodel_list_t *models = NULL;
static esp_afe_sr_iface_t *afe_handle = NULL;
static esp_afe_sr_data_t *afe_data = NULL;

int detect_flag = 0;
static volatile int task_flag = 0;

// // AI人动画
// LV_IMG_DECLARE(astronaut_spins);

// // AI人动画
// LV_IMG_DECLARE(img_bilibili120);
// lv_obj_t *gif_start;
// LV_IMG_DECLARE(author);
// // AI人出现在屏幕
// void ai_gui_in(void)
// {

//     lvgl_port_lock(0);
//     ESP_LOGI(TAG, "Free heap: %d", esp_get_free_heap_size());
//     ESP_LOGI(TAG, "Largest free block: %d", heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT));
//     gif_start = lv_gif_create(lv_scr_act());
//     // gif_start = lv_img_create(lv_scr_act());
//     lv_gif_set_src(gif_start, &astronaut_spins);
//     // lv_img_set_src(gif_start, &author);
//     lv_obj_align(gif_start, LV_ALIGN_CENTER, 0, 0);
//     // 确保对象可见
// //    lv_obj_set_hidden(gif_start, false);
//     lv_obj_invalidate(gif_start); // 强制重绘
//     lvgl_port_unlock();
// }

// // AI人退出屏幕
// void ai_gui_out(void)
// {
//     lvgl_port_lock(0);
//     lv_obj_del(gif_start);
//     lvgl_port_unlock();
// }

void feed_Task(void *arg)
{
    esp_afe_sr_data_t *afe_data = arg;  // 获取参数
    int audio_chunksize = afe_handle->get_feed_chunksize(afe_data); // 获取帧长度
    int nch = afe_handle->get_channel_num(afe_data); // 获取声道数
    int feed_channel = bsp_get_feed_channel(); // 获取ADC输入通道数
    assert(nch <= feed_channel);
    int16_t *i2s_buff = heap_caps_malloc(audio_chunksize * sizeof(int16_t) * feed_channel, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); // 分配获取I2S数据的缓存大小
    assert(i2s_buff);

    while (task_flag) {
        esp_err_t ret = bsp_get_feed_data(false, i2s_buff, audio_chunksize * sizeof(int16_t) * feed_channel);  // 获取I2S数据
        //ESP_LOGI(TAG, "feed_Task get data err:%d", ret);
        // if(ret!= ESP_OK)
        //     break;
        afe_handle->feed(afe_data, i2s_buff); // 把获取到的I2S数据输入给afe_data
        if (carry_command)
            vTaskDelay(pdMS_TO_TICKS(100)); // 延时10ms
    }
    if (i2s_buff) {
        free(i2s_buff);
        i2s_buff = NULL;
    }
    vTaskDelete(NULL);
}

void detect_Task(void *arg)
{
    esp_afe_sr_data_t *afe_data = arg;  // 接收参数
    int afe_chunksize = afe_handle->get_fetch_chunksize(afe_data);  // 获取fetch帧长度
    char *mn_name = esp_srmodel_filter(models, ESP_MN_PREFIX, ESP_MN_CHINESE); // 初始化命令词模型
    printf("multinet:%s\n", mn_name); // 打印命令词模型名称
    esp_mn_iface_t *multinet = esp_mn_handle_from_name(mn_name);
    model_iface_data_t *model_data = multinet->create(mn_name, 6000);  // 设置唤醒后等待事件 6000代表6000毫秒
    esp_mn_commands_clear(); // 清除当前的命令词列表
    esp_mn_commands_add(1, "da kai luo ji fen xi yi"); // 打开逻辑分析仪
    esp_mn_commands_add(2, "da kai yin yue");          // 打开音乐
    esp_mn_commands_add(3, "da kai sd ka");            // 打开SD卡
    esp_mn_commands_add(4, "da kai kong tiao");        // 打开空调
    esp_mn_commands_add(5, "da kai wu xian tiao shi"); // 打开无线调试
    esp_mn_commands_update(); // 更新命令词

    int mu_chunksize = multinet->get_samp_chunksize(model_data);  // 获取samp帧长度
    assert(mu_chunksize == afe_chunksize);
    ESP_LOGI(TAG, "mu_chunksize:%d, afe_chunksize:%d", mu_chunksize, afe_chunksize);
    // 打印所有的命令
    multinet->print_active_speech_commands(model_data);
    printf("------------detect start------------\n");

    while (task_flag) {
        afe_fetch_result_t* res = afe_handle->fetch(afe_data); // 获取模型输出结果
        if (!res || res->ret_value == ESP_FAIL) {
            printf("fetch error!\n");
            break;
        }
        if (res->wakeup_state == WAKENET_DETECTED) {
            printf("WAKEWORD DETECTED\n");
	        multinet->clean(model_data);  // clean all status of multinet
        } else if (res->wakeup_state == WAKENET_CHANNEL_VERIFIED) {  // 检测到唤醒词
            // play_voice = -1;
            afe_handle->disable_wakenet(afe_data);  // 关闭唤醒词识别
            detect_flag = 1; // 标记已检测到唤醒词
          //  ai_gui_in(); // AI人出现
           // printf("AFE_FETCH_CHANNEL_VERIFIED, channel index: %d\n", res->trigger_channel_id);
        }

        if (detect_flag == 1) {
            esp_mn_state_t mn_state = multinet->detect(model_data, res->data); // 检测命令词

            if (mn_state == ESP_MN_STATE_DETECTING) {//
                continue;
            }

            if (mn_state == ESP_MN_STATE_DETECTED) { // 已检测到命令词
                esp_mn_results_t *mn_result = multinet->get_results(model_data); // 获取检测词结果
                for (int i = 0; i < mn_result->num; i++) { // 打印获取到的命令词
                    printf("TOP %d, command_id: %d, phrase_id: %d, string:%s prob: %f\n", 
                    i+1, mn_result->command_id[i], mn_result->phrase_id[i], mn_result->string, mn_result->prob[i]);
                }
                /*要开始执行相应的动作了，可能来不及fetch*/
                carry_command = true;
                // 根据命令词 执行相应动作
                switch (mn_result->command_id[0]) {
                    
                    case 1: // 打开逻辑分析仪
                        ESP_LOGI(TAG, "open logic analyzer");
                        exit_current_func_ui();
                        vTaskDelay(pdMS_TO_TICKS(200));
                        load_func_ui(FUNC_LOGIC_ANALYZER);
                        break;
                    case 2: //打开音乐
                        ESP_LOGI(TAG, "open music");
            
                        break;
                    case 3: //打开SD卡
                        ESP_LOGI(TAG, "open sdcard");
                        break;
                    case 4: // 打开空调
                        ESP_LOGI(TAG, "open air conditioner");
                        break;
                    case 5: // 打开无线调试
                        ESP_LOGI(TAG, "open wireless debug");
                        break;

                    default:
                        break;
                }
                printf("\n-----------listening-----------\n");
                carry_command = false;
            }

            if (mn_state == ESP_MN_STATE_TIMEOUT) { // 达到最大检测命令词时间
                esp_mn_results_t *mn_result = multinet->get_results(model_data);
                printf("timeout, string:%s\n", mn_result->string);
                afe_handle->enable_wakenet(afe_data);  // 重新打开唤醒词识别
                detect_flag = 0; // 清除标记
                printf("\n-----------awaits to be waken up-----------\n");
               // ai_gui_out(); // AI人退出
                continue;
            }
        }
    }
    if (model_data) {
        multinet->destroy(model_data);
        model_data = NULL;
    }

    printf("detect exit\n");
    vTaskDelete(NULL);
}

void app_sr_init(void)
{
    renew_codec_fs();                   //恢复语音控制的i2s配置
    models = esp_srmodel_init("model"); // 获取模型 名称“model”和分区表中装载模型的名称一致

    afe_handle = (esp_afe_sr_iface_t *)&ESP_AFE_SR_HANDLE;  // 先配置afe句柄 随后才可以调用afe接口
    afe_config_t afe_config = AFE_CONFIG_DEFAULT(); // 配置afe

    afe_config.wakenet_model_name = esp_srmodel_filter(models, ESP_WN_PREFIX, NULL); // 配置唤醒模型 必须在create_from_config之前配置
    afe_data = afe_handle->create_from_config(&afe_config); // 创建afe_data
    ESP_LOGI(TAG, "wakenet:%s", afe_config.wakenet_model_name); // 打印唤醒名称

    task_flag = 1;
    xTaskCreatePinnedToCoreWithCaps(&detect_Task, "detect", 8 * 1024, (void *)afe_data, 5, NULL, 1, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
    xTaskCreatePinnedToCoreWithCaps(&feed_Task, "feed", 8 * 1024, (void *)afe_data, 5, NULL, 0, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
    // xTaskCreatePinnedToCore(&detect_Task, "detect", 8 * 1024, (void *)afe_data, 5, NULL, 1); // 创建检测任务
    // xTaskCreatePinnedToCore(&feed_Task, "feed", 8 * 1024, (void*)afe_data, 5, NULL, 0);// 创建获取I2S数据任务
}

void app_sr_deinit(void)
{
    task_flag = 0;
    if (models)
        esp_srmodel_deinit(models);
    models = NULL;

}

static uint32_t g_rate;
static uint8_t g_bits_cfg, g_ch;
static void (*g_enter_cb)(void)=NULL;
static void (*g_exit_cb)(void) = NULL;
// 音乐
static void
reminder_confirm_cb(lv_event_t *e)
{
    lv_obj_t *msgbox = lv_event_get_current_target(e);
    uint16_t btn_id = lv_msgbox_get_active_btn(msgbox);
    // // 获取用户数据中的回调函数
    // void (*enter_cb)(void) = (void (*)(void))lv_obj_get_user_data(msgbox);
    // // 1. 获取关闭按钮对象
    // lv_obj_t *close_btn = lv_msgbox_get_close_btn(msgbox);
    // 1. 获取关闭按钮对象
    lv_obj_t *close_btn = lv_msgbox_get_close_btn(msgbox);
    // 2. 发送点击事件
    if (close_btn) {
        lv_event_send(close_btn, LV_EVENT_CLICKED, NULL);
    }

    if (btn_id == 0) { // 用户点击了"确认"
        if (g_enter_cb) {
            g_enter_cb();
            g_enter_cb = NULL;
        }
        app_sr_deinit();
        bsp_codec_set_fs(g_rate, g_bits_cfg, g_ch); // 设置音频参数为用户设置参数
    }else if (btn_id == 1)  // 用户点击了"取消"
    {
        if (g_exit_cb) {
            g_exit_cb();
            g_exit_cb = NULL;
        }
    }
    // // refresh_settings_ui();
    // if (msgbox)
    // {

    //     // // 使用异步删除，确保安全
    //     // lv_obj_del(msgbox);
    //     lv_msgbox_close(msgbox);
    //     msgbox = NULL;
    // }

}
void reminder_voice_clash_ui(uint32_t rate, uint8_t bits_cfg, uint8_t ch, void (*enter_cb)(void), void (*exit_cb)(void))
{
    g_rate = rate;
    g_bits_cfg = bits_cfg;
    g_ch = ch;
    g_enter_cb = enter_cb;
    g_exit_cb = exit_cb;
    static const char *btns[3];
    btns[0] = get_reminder_txt_data(REMINDER_CONTINUE);
    btns[1] = get_reminder_txt_data(REMINDER_EXIT);
    btns[2] = "";

    lv_obj_t *msgbox = lv_msgbox_create(lv_scr_act(),
                                        get_reminder_txt_data(REMINDER_VOICN_TITLE),
                                        get_reminder_txt_data(REMINDER_VOICN_TXT),
                                        btns, true);

    // 设置对话框样式
    lv_obj_set_style_bg_color(msgbox, lv_color_hex(get_screen_color_val()), LV_PART_MAIN);
    lv_obj_set_style_text_color(msgbox, get_btn_font_color(), LV_PART_MAIN);
    lv_obj_set_style_text_font(msgbox, &myFont, LV_PART_MAIN);

    lv_obj_t *btnm = lv_msgbox_get_btns(msgbox);
    if (btnm) {
        // 设置按钮之间的水平间距（
        lv_obj_set_style_pad_column(btnm, 30, LV_PART_MAIN);

        // 设置按钮的内边距（，使按钮更大）
        lv_obj_set_style_pad_hor(btnm, 8, LV_PART_ITEMS);
    }

    // 设置提示文字样式 - 红色
    lv_obj_t *txt = lv_msgbox_get_text(msgbox);
    if (txt) {
        lv_obj_set_style_text_color(txt, lv_color_hex(0xFF0000), LV_PART_MAIN); // 红色提示文字
    }
    // 获取关闭按钮对象
    lv_obj_t *close_btn = lv_msgbox_get_close_btn(msgbox);

    // 设置包含关闭图标字符的字体
    lv_obj_set_style_text_font(close_btn, &lv_font_montserrat_14, LV_PART_MAIN);

    // 调整关闭按钮大小以确保图标可见
    lv_obj_set_size(close_btn, 32, 32);

    // 设置文本颜色
    lv_obj_set_style_text_color(close_btn, get_btn_font_color(), LV_PART_MAIN);
    lv_obj_set_user_data(msgbox, (void *)enter_cb);
    // 添加事件回调，传递开关对象作为用户数据
    lv_obj_add_event_cb(msgbox, reminder_confirm_cb, LV_EVENT_VALUE_CHANGED, NULL);

    // 居中显示对话框
    lv_obj_center(msgbox);
}
